<?php

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 * Description of HttpModel
 * @date 2012-12-14
 * @author Clive
 */
function array_add(&$row, $addrow, $filter = '') {
    if ($filter == '') {
        foreach ($addrow as $key => $val) {
            $row[$key] = $val;
        }
    } else {
        $arr = explode(',', $filter);
        foreach ($arr as $val) {
            $row[$val] = $addrow[$val];
        }
    }
}

class http {

//put your code here
    public $url = "";
    public $timeout = 0;
    public $debuglevel = 0; //0：关闭调试，1：打开状态，2：显示数据
    public $status = 0;
    private $startlevel = 0;
    public $header = array();

    public function __construct() {
        $this->timeout_conn = 2; //连接超时
        $this->timeout_fp = 10; //下载超时
    }

    public function getcontent($charset = 'utf-8') {
        $url = parse_url($this->url);
        if (is_array($this->header)) {
            $header = array();
            $header['Host'] = $url['host'];
            $header['URI'] = $url['path'] . '?' . $url['query'];
            array_add($header, $this->header);
        } else {
            $header = $this->header;
        }
        $content = '';
        $host = $url['host'];
        if ($url['scheme'] != 'http')
            $host = $url['scheme'] . '://' . $host;
        if (!isset($url['port']))
            $url['port'] = 80;
        $this->status = $this->get_http_info($host, $url['port'], $header, $content);
        $content = iconv('utf-8', $charset, $content);
        return($content);
    }

    public function get_http_info($ip, $port, &$header, &$content) {
        $errno = 0;
        $errstr = '';
        $this->debugstart(1, 'connecting to [' . $ip . ':' . $port . ']');
        $fp = fsockopen($ip, $port, $errno, $errstr, $this->timeout_conn); //199.36.73.39
        if (!$fp) {
            return(-1); //错误：无法连接
        }
        $this->debugok();
        $data = '';
        if (is_array($header)) {
            if (!isset($header['User-Agent']))
                $header['User-Agent'] = 'Mozilla/5.0 (Windows NT 5.2; rv:10.0.2) Gecko/20100101 Firefox/10.0.2';
            if (!isset($header['Accept']))
            //$header['Accept'] = 'image/png,image/*;q=0.8,*/*;q=0.5';
                $header['Accept'] = '*/*';
            if (!isset($header['Accept-Language']))
                $header['Accept-Language'] = 'zh-cn,zh;q=0.5';
            if (!isset($header['Accept-Encoding']))
                $header['Accept-Encoding'] = 'gzip, deflate';
            if (!isset($header['Connection']))
                $header['Connection'] = 'keep-alive';
            if (!isset($header['Pragma']))
                $header['Pragma'] = 'no-cache';
            if (!isset($header['Cache-Control']))
                $header['Cache-Control'] = 'no-cache';
            $httpType = 'GET';
            if (isset($header['Post'])) {
                $httpType = 'POST';
            }
            $data = $httpType . ' ' . $header['URI'] . " HTTP/1.1\r\n";
            foreach ($header as $key => $value) {
                if ($key == 'Post' || $key == 'URI') {
                    
                } else {
                    $data.="{$key}: {$value}\r\n";
                }
            }
            if (isset($header['Post'])) {
                $data.='Content-Type: application/x-www-form-urlencoded' . "\r\n";
                $data.='Content-Length: ' . strlen($header['Post']) . "\r\n";
            }
        } else {
            $data = $header;
        }
        $this->debugstart(3, 'print($header)');
        $this->debugprintr(3, $data);
        $this->debugok();
        if (is_array($header)) {
            $data.="\r\n";
            if (isset($header['Post'])) {
                $data.=$header['Post'];
            }
        }
//echo $data;
        $this->debugstart(1, 'send Header AND Post...');
        fwrite($fp, $data);
        $this->debugok();
        stream_set_timeout($fp, $this->timeout_fp);
//====已提交上去了！下面开始获取数据=========
        $this->debugstart(1, "get header...");
        $header = '';
        while (!feof($fp)) {
            $line = fgets($fp);
            if ($line == "\r\n") {
                break;
            }
            $header.=$line;
            $info = stream_get_meta_data($fp);
            if ($info['timed_out']) {
                $this->debugprint(1, 'get header timed_out');
                break;
            }
        }
        $header = explode("\r\n", $header);
        $this->debugprintr(2, $header);
        $http0 = $header[0];
        $header = $this->getArrFromPreArr($header, ': ', 1);
        $header['http0'] = $http0;
        $this->debugok();
        if (isset($header['Content-Length'])) {
            $content_length = intval($header['Content-Length']);
            if ($content_length == 0) {
                return(-2); //错误：无内容
            }
            $content = '';
//echo 'content_length='.$content_length.';';
            $fread_length = 1024;
            if ($content_length < $fread_length) {
                $fread_length = $content_length;
            }
            $this->debugprint(1, 'get content...');
            while (!feof($fp)) {
                $line = fread($fp, $fread_length);
                $content.=$line;
                $surplus_length = $content_length - strlen($content);
                if ($surplus_length < $fread_length) {
                    $fread_length = $surplus_length;
                }
//echo strlen($content).'.';
                if (strlen($content) >= $content_length) {
                    break;
                }
                $info = stream_get_meta_data($fp);
                if ($info['timed_out']) {
                    $this->debugprint(1, 'the contents timed_out');
                    break;
                }
            }
            $this->debugok();
        } else {
            $this->debugprint(1, 'no [Content-Length]');
            if (1) {
                $content = stream_get_contents($fp);
                $info = stream_get_meta_data($fp);
                if ($info['timed_out']) {
                    $this->debugprint(1, 'the [stream_get_contents] timed_out');
                }
            }
        }
        fclose($fp);
        $ContentEncoding = isset($header['Content-Encoding']) ? $header['Content-Encoding'] : '';
        if ($ContentEncoding == 'gzip') {
            $content = $this->gzdecode($this->chunked_decode($content));
        }
        $this->debugprint(3, '[' . $content . ']');
        return(1);
    }

    function getArrFromPreArr($rnArr, $symbol2 = '=', $decode = 0) {
//用于读取COOKIE或HEADER里的字符串
        $outarr = array();
        foreach ($rnArr as $rnRow) {
//检测是否存在[=]号，如果存在就标出位置
            if (is_int($i = strpos($rnRow, $symbol2))) {
                $symbol2Len = strlen($symbol2);
                $newdata = substr($rnRow, $i + $symbol2Len, strlen($rnRow) - $i + $symbol2Len);
                if ($decode == 1) {
                    $newdata = urldecode($newdata);
                }
//到这里已经取到[$newdata]，下面要判断如何放进去
                $name = substr($rnRow, 0, $i); //数组的key
                if (isset($outarr[$name])) {
//如果数组已经存在
                    $data = $outarr[$name];
                    if (count($data) == 1) {
//如果是字符串，那就转换成数组
                        $outarr[$name] = array();
                        $outarr[$name][] = $data;
                    }
//把新的数组加进去(现在是2个了)
                    $outarr[$name][] = $newdata;
                } else {
                    $outarr[$name] = $newdata;
                }
            }
        }
        return($outarr);
    }

    public function setCookieListToArr($setCookieList, &$out_cookie) {
        if ($setCookieList == '')
            return(0);
        if (count($setCookieList) >= 2) {
            foreach ($setCookieList as $setcookie) {
                $cookieArr = explode('; ', $setcookie);
                $cookieRow = explode('=', $cookieArr[0]);
                $out_cookie[$cookieRow[0]] = $cookieRow[1];
            }
        } else {
            $setcookie = $setCookieList;
            $cookieArr = explode('; ', $setcookie);
            $cookieRow = explode('=', $cookieArr[0]);
            $out_cookie[$cookieRow[0]] = $cookieRow[1];
        }
        return(1);
    }

    private function debugprint($level, $content) {
        if ($this->debuglevel >= $level) {
            echo 'httpalert: ' . $content . "\r\n";
        }
    }

    private function debugprintr($level, $content) {
        if ($this->debuglevel >= $level) {
            echo "\r\n";
            print_r($content);
            echo "\r\n";
        }
    }

    private function debugstart($level, $content) {
        if ($this->debuglevel >= $level) {
            $this->startlevel = $level;
            echo 'httpalert: ' . $content;
        }
    }

    private function debugok() {
        if ($this->debuglevel > 0 && $this->debuglevel >= $this->startlevel)
            echo "ok!\r\n";
    }

    private function chunked_decode($in) {
        $out = '';
        while ($in != '') {
            $lf_pos = strpos($in, "\012");
            if ($lf_pos === false) {
                $out .= $in;
                break;
            }
            $chunk_hex = trim(substr($in, 0, $lf_pos));
            $sc_pos = strpos($chunk_hex, ';');
            if ($sc_pos !== false)
                $chunk_hex = substr($chunk_hex, 0, $sc_pos);
            if ($chunk_hex == '') {
                $out .= substr($in, 0, $lf_pos);
                $in = substr($in, $lf_pos + 1);
                continue;
            }
            $chunk_len = hexdec($chunk_hex);
            if ($chunk_len) {
                $out .= substr($in, $lf_pos + 1, $chunk_len);
                $in = substr($in, $lf_pos + 2 + $chunk_len);
            } else {
                $in = '';
            }
        }
        return $out;
    }

    private function gzdecode($data) {
        $flags = ord(substr($data, 3, 1));
        $headerlen = 10;
        $extralen = 0;
        $filenamelen = 0;
        if ($flags & 4) {
            $extralen = unpack('v', substr($data, 10, 2));
            $extralen = $extralen [1];
            $headerlen += 2 + $extralen;
        }
        if ($flags & 8) // Filename  
            $headerlen = strpos($data, chr(0), $headerlen) + 1;
        if ($flags & 16) // Comment  
            $headerlen = strpos($data, chr(0), $headerlen) + 1;
        if ($flags & 2) // CRC at end of file  
            $headerlen += 2;
        $unpacked = @gzinflate(substr($data, $headerlen));
        if ($unpacked === FALSE)
            $unpacked = $data;
        return $unpacked;
    }

}

?>
